package cevent.source.cloudcenter.source.controller.admin;/**
 * Created by Cevent on 2021/5/10.
 */

import cevent.source.cloudcenter.server.dto.FileDto;
import cevent.source.cloudcenter.server.dto.ResponseDataDto;
import cevent.source.cloudcenter.server.enums.UseTypeEnum;
import cevent.source.cloudcenter.server.service.FileService;
import cevent.source.cloudcenter.server.util.Base64ToMultipartFile;
import cevent.source.cloudcenter.server.util.VODUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse;
import com.aliyuncs.vod.model.v20170321.GetMezzanineInfoResponse;
import com.aliyuncs.vod.model.v20170321.GetVideoPlayAuthResponse;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author cevent
 * @description 加密文件上传
 * @date 2021/5/10 22:37
 */
@RestController
@RequestMapping("/admin")
public class VODController {
    public static final Logger LOG= LoggerFactory.getLogger(VODController.class);
    public static final String BUSINESS_NAME="阿里云VOD文件加密上传";

    @Value("${vod.accessKeyID}")
    private String VOD_ACCESS_KEY_ID;
    @Value("${vod.accessKeySecret}")
    private String VOD_ACCESS_KEY_SECRET;
    @Value("${vod.catID}")
    private String VOD_CAT_ID;
    @Value("${vod.transferID}")
    private String VOD_TRANSFER_ID;
    @Resource
    FileService fileService;

    //2.追加上传
    @RequestMapping("/vod-simple")
    public ResponseDataDto uploadAppendOSS(@RequestBody FileDto fileDto) throws IOException, InterruptedException {

        String useType = fileDto.getUseType();
        //获取枚举类型，生成新的文件夹路径
        UseTypeEnum useTypeEnum = UseTypeEnum.getByCode(useType);
        LOG.info("传入的useType：{}", useType);
        String fileName=fileDto.getName();
        LOG.info("传入的fileName：{}",fileName);
        String name=fileName.substring(0,fileName.lastIndexOf("."));
        LOG.info("截取的name：{}",name);
        String suffix=fileName.substring(fileName.lastIndexOf(".")+1).toLowerCase();
        LOG.info("截取的后缀：{}",suffix);
        LOG.info("传入的fileDto：{}",fileDto);
        LOG.info("传入的module_id：{}",fileDto.getModuleId());
        fileDto.setName(name+"."+suffix);
        Integer shardIndex=fileDto.getShardIndex();
        Integer shardSize=fileDto.getShardSize();
        String shardBase64 = fileDto.getShard();
        MultipartFile shard = Base64ToMultipartFile.base64TransToMultipartFile(shardBase64);
        Date now = new Date();
        String date = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(now);
        String dateDir = new SimpleDateFormat("yyyy_MM_dd").format(now);
        String dir = useTypeEnum.name().toLowerCase();
        /**
         * File.separator生成不同操作系统的/斜杠
         * 更新分片传入，将每个分片文件后缀改为xx.mp4.shardIndex
         * 注意：阿里云OSS文件判断，文件名携带唯一key即可，如果加入时间戳，无法获取到下一次append的文件名
         */
        String path = new StringBuffer(date).append("_")
                .append(dir).append("_")
                .append(fileDto.getShardKey()).append("_")
                .append(name).append(".").append(suffix)
                .toString();
        LOG.info("VOD传输--》上传的path：{}", path);

        /**
         * OSS文件上传
         */
        String fileURL="";
        String videoId="";
        try {
            //1.初始化acs客户端，获取authority权限
            DefaultAcsClient acsClient= VODUtil.initVODClient(VOD_ACCESS_KEY_ID,VOD_ACCESS_KEY_SECRET);
            //3.创建响应：客户端和文件
            CreateUploadVideoResponse uploadVideoResponse=VODUtil.createUploadVideoResponse(acsClient,path);
            //传入vodID
            videoId=uploadVideoResponse.getVideoId();
            //5.需要将上传响应的结果，转换为JSONObject对象
            JSONObject accessAuthority=JSONObject.parseObject(
                    Base64.decodeBase64(uploadVideoResponse.getUploadAuth()),JSONObject.class);
            JSONObject accessEndPoint=JSONObject.parseObject(
                    Base64.decodeBase64(uploadVideoResponse.getUploadAddress()),JSONObject.class);
            LOG.info("这里的accessEndPoint：{}",accessEndPoint);
            //6.使用Auth和Address初始化OSS客户端
            OSSClient ossClient=VODUtil.initialOSSClient(accessAuthority,accessEndPoint);
            LOG.info("这里的OSSClient：{}",ossClient);
            //7.上传文件，同步上传会阻塞等待，耗时与文件大小和网络带宽有关
            VODUtil.uploadOSSLocalFile(ossClient,accessEndPoint,shard.getInputStream());

            //8.获取响应中间层：视频信息
            GetMezzanineInfoResponse mezzanineInfoResponse=new GetMezzanineInfoResponse();
            mezzanineInfoResponse=VODUtil.getMezzanineInfoResponse(acsClient,videoId);
            //&& 阿里云jar里的实体类没有重写toString方法，每次打印日志都需要JSON.toString，所以实体类最好都加上toString
            LOG.info("VOD视频上传成功！获取视频信息mezzanine info response: {}", JSON.toJSONString(mezzanineInfoResponse));
            //4.响应中间层mezzanine中获取参数
            videoId=mezzanineInfoResponse.getMezzanine().getVideoId();
            fileURL=mezzanineInfoResponse.getMezzanine().getFileURL();
        } catch (ClientException e) {
            LOG.info("上传视频失败 --！: {}",e.getLocalizedMessage());
            e.printStackTrace();
        }
        fileDto.setPath(fileURL);
        fileDto.setName(path);
        fileDto.setVod(videoId);
        fileDto.setIsShow(0);
        fileService.save(fileDto);
        ResponseDataDto responseData = new ResponseDataDto();
        responseData.setResponseData(fileDto);
        return responseData;
    }

    //获取vod -> videoId 进行加密播放授权
    @RequestMapping(value="/get-vod/{vod}",method = RequestMethod.GET)
    public ResponseDataDto getVodAuth(@PathVariable String vod){
        ResponseDataDto responseData=new ResponseDataDto();
        //初始化acsClient客户端
        DefaultAcsClient acsClient=VODUtil.initVODClient(VOD_ACCESS_KEY_ID,VOD_ACCESS_KEY_SECRET);
        GetVideoPlayAuthResponse authResponse=new GetVideoPlayAuthResponse();
        try {
            //根据传入的videoId获取播放凭证
            authResponse=VODUtil.getVideoPlayAuthResponse(acsClient,vod);
            LOG.info("授权码={}",authResponse.getPlayAuth());
            //回传的responseData只有授权码信息
            responseData.setResponseData(authResponse.getPlayAuth());
            //输出视频信息
            LOG.info("VideoMeta={}",JSONObject.toJSONString(authResponse.getVideoMeta()));
        } catch (ClientException e) {
            LOG.info("获取播放授权失败：{}",e.getLocalizedMessage());
            e.printStackTrace();
        }

        return responseData;
    }
}
